.TITLE CORAL .IDENT /10.12/ ; ; Copyright (c) 1995-1999 by Mentec Inc., U.S.A. ; All rights reserved. ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; D. N. CUTLER 3-AUG-73 ; ; MODIFIED BY: ; ; H. HUANG 28-JUN-83 10.00 ; ; HH175 -- ADD EXTENDIBLE SECONDARY POOL SUPPORT ; ; J. W. BERZLE 07-SEP-83 10.01 ; ; JWB047 -- ADD BUGCHECK FACILITY AND ERROR CODES ; ; J. W. BERZLE 11-JUN-84 10.02 ; ; JWB085 -- DEALLOCATE CONTEXT BLOCK IF PRESENT ; WHEN DEALLOCATING CLOCK BLOCK ; ; C. A. SILVER 12-MAR-85 10.03 ; ; CAS019 -- ADD AUXILARY SPM HOOKPOINTS ; ; C. B. PUTNAM 09-MAY-85 10.04 ; ; CBP204 -- ADD POOL FRAGMENT VALIDITY CHECK ; ; B. S. MCCARTHY 24-JUN-85 10.05 ; ; CAS019 -- REFORMAT SPM HOOK COMMENTS ; ; P. K. M. WEISS 13-OCT-86 10.06 ; ; PKW118 -- ADD $ALSC1 AND $DESC1 ENTRY POINTS ; ; P. K. M. WEISS 10-NOV-87 10.07 ; ; PKW142 - RETURN CC WHEN LISTHEAD BELOW $POLHD FOR $ALSC1 ; ; P. K. M. WEISS 2-FEB-88 10.08 ; ; PKW150 - CALL $CPRCV IF $CPPOL IS SET ON POOL DEALLOCATION ; ; P. K. M. WEISS 29-NOV-88 10.09 ; ; PKW168 - $SAVAL IS *NOT* AN EXEC ROUTINE, CRETIN ; ; D. CARROLL 17-JUN-1993 10.10 ; ; DC228 -- ALLOW USE OF ICB POOL FOR PRIMARY POOL IF ; ALLOCATION FAILURE OCCURS. ; ; D. CARROLL 26-APRIL-1995 10.11 ; DC359 -- Correct pool allocation failure reporting, and ; handle PLCTL high/low values with 100000 indicating ; to use ICB pool as the limit. ; ; Modified for RSX-11M-PLUS V4.6 by: ; ; D. Carroll 18-Oct-1995 10.12 ; DC404 - Include PSECT definition to allow ICB pool to be ; fully expanded when desired ; ; ; CORE BUFFER ALLOCATION ROUTINES ; ; MACRO LIBRARY CALLS ; .MCALL CLKDF$,PKTDF$,BGCK$A CLKDF$ ;DEFINE CLOCK QUEUE CONTROL BLOCK OFFSETS PKTDF$ ;DEFINE I/O PACKET OFFSETS .IIF DF,K$$DAS&I$$CBP, .PSECT EXEC1 ;DC404 ;DC404 .IF DF,I$$CBP&K$$DAS&M$$PRO .IIF NE,, .ERROR ; NOT SUPPORTED ICB POOL ON MP SYSTEM .ENDC ;DF,I$$CBP&K$$DAS&M$$PRO ;+ ; **-$ALOCB-ALLOCATE CORE BUFFER ; **-$ALOC1-ALLOCATE CORE BUFFER (ALTERNATE ENTRY) ; ; THIS ROUTINE IS CALLED TO ALLOCATE AN EXEC CORE BUFFER. THE ALLOCATION ; ALGORITHM IS FIRST FIT AND BLOCKS ARE ALLOCATED IN MULTIPLES OF FOUR ; BYTES. ; ; INPUTS: ; ; R0=ADDRESS OF CORE ALLOCATION LISTHEAD-2 IF ENTRY AT $ALOC1. ; R1=SIZE OF THE CORE BUFFER TO ALLOCATE IN BYTES. ; ; OUTPUTS: ; ; C=1 IF INSUFFICIENT CORE IS AVAILABLE TO ALLOCATE THE BLOCK. ; C=0 IF THE BLOCK IS ALLOCATED. ; R0=ADDRESS OF THE ALLOCATED BLOCK. ; R1=LENGTH OF BLOCK ALLOCATED ;- .ENABL LSB $ALOCB::MOV #$CRAVL-2,R0 ;POINT TO ALLOCATION MASK WORD .IF DF Q$$OPT ADD (R0),R1 ;ROUND TO NEXT BOUNDARY BIC (R0)+,R1 ; BEQ 5$ ;IF EQ ZERO LENGTH REQUEST CMP R1,#I.LGTH ;REQUEST SIZE OF PACKET? BNE 5$ ;IF NE NO MOV #$PKAVL,R2 ;POINT TO PACKET AVAILABLE POINTER MOV (R2),R0 ;PICK UP PACKET POINTER BEQ 4$ ;IF EQ THERE IS NONE MOV (R0),(R2)+ ;UNLINK PACKET FROM LIFO LIST ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 77. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH77==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL DEC (R2) ;INDICATE ONE PACKET LESS IN LIST RETURN ; 4$: MOV #$CRAVL-2,R0 ;POINT BACK TO ALLOCATION MASK WORD .ENDC $ALOC1::ADD (R0),R1 ;ROUND TO NEXT BOUNDARY BIC (R0)+,R1 ;CLEAR EXCESS 5$: SEC ;ASSUME ZERO LENGTH BLOCK BEQ 35$ ;IF EQ ZERO LENGTH REQUEST .IF DF P$$CTL MOV R0,-(SP) ;SAVE ADDRESS OF LISTHEAD .IF DF I$$CBP&K$$DAS CMP R0,#$CRAVL ; IS THIS THE EXEC LISTHEAD? BEQ 7$ ; IF EQ, YES, FLAG AS SUCH CMP R0,#$ICAVL ; HOW ABOUT ICB POOL? BNE 8$ ; IF NE, NOPE, GO DO THE WORK CLR (SP) ; FLAG ICB POOL USAGE 7$: INC (SP) ; FLAG TRACKABLE POOL 8$: SEC ; INSURE CARRY SET .ENDC ;DF,I$$CBP&K$$DAS .ENDC 10$: MOV R0,R2 ;SAVE ADDRESS OF CURRENT BLOCK MOV (R2),R0 ;GET ADDRESS OF NEXT BLOCK .IF DF R$$DER BEQ 40$ ;IF EQ END OF CHAIN ; ;THE FOLLOWING CODE CHECKS TO SEE IF THE POOL ;...FRAGMENT IS OF VALID SIZE. IT CAN BE ;...NEITHER ODD NOR AN ODD MULTIPLE OF 2 BYTES ; BIT #3,2(R0) ;FRAGMENT SIZE VALID? BNE 50$ ;IF NE, NO .IFF BEQ 30$ ;IF EQ END OF CHAIN .ENDC CMP 2(R0),R1 ;BLOCK BIG ENOUGH? BLO 10$ ;IF LO NO BEQ 20$ ;IF EQ BLOCK IS EXACT SIZE TST (R0)+ ;POINT TO SIZE OF FREE BLOCK SUB R1,(R0) ;CALCULATE SIZE REMAINING ADD R0,R1 ;POINT TO NEW FREE BLOCK MOV (R0),(R1) ;COPY SIZE MOV -(R0),-(R1) ;COPY LINK MOV R1,(R0) ;STORE LINK TO NEW FREE BLOCK SUB R0,R1 ;RESTORE SIZE OF BLOCK 20$: MOV (R0),(R2) ;UPDATE LINK TO NEW FREE BLOCK 30$: ; .IF DF P$$CTL .IF DF I$$CBP&K$$DAS ROR (SP) ; IS THIS A TRACKABLE POOL? BCC 34$ ; IF CC, NOPE, RETURN STATUS .IFF ;DF,I$$CBP&K$$DAS BIT #^C<$CRAVL>,(SP)+ ;ALLOCATION FROM EXEC'S POOL? BNE 35$ ;IF NE NO, SKIP POOL SIZE TRACKING ROR (R0) ;ALLOCATION FAILURE? (SAVE C-BIT) .IFTF ;DF,I$$CBP&K$$DAS BPL 32$ ;IF PL NO .IFT ;DF,I$$CBP&K$$DAS BIT #F6.ICP,$FMSK6 ; HAS THIS FUNCTION BEEN DISABLED? BEQ 31$ ; IF EQ, YES, RETURN THE ERROR ;+ ; Note: For a caller who is requesting *only* ICB pool, and not ; an original request for $CRAVL, a pool allocation failure will not ; be reported to PMT... for tracking. The failure will only occur if ; the original request was made of normal primary pool, and a failure ; occured on both possible pools. ;- ASL (SP)+ ; IS THIS ATTEMPT FOR ICB POOL? BEQ 35$ ; IF EQ, YES, RETURN FINAL STATUS, ERROR MOV #$ICAVL-2,R0 ; SET UP THE ICB POOL LISTHEAD CALL $ALOC1 ; AND TRY AGAIN ... ROR -(SP) ; SAVE STATUS OF CARRY BMI 31$ ; IF MI, FULL ALLOCATION ERROR TST $PRILL ; IS ICB POOL THE LOW LIMIT? BPL 34$ ; IF PL, NOPE BR 325$ ; REPORT THE POOL CHANGE 31$: .IFTF ;DF,I$$CBP&K$$DAS MOV #PC.ALF!,R2 ;SET LOW POOL MASK BR 33$ ;REPORT THE ALLOCATION FAILURE 32$: SUB R1,$PRISZ ;SUBTRACT FROM TOTAL FREE POOL SIZE ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 76. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH76==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL CMP @#$PRISZ,@#$PRILL ;DID WE CROSS LOWER POOL LIMIT? BGE 34$ ;IF HIS NO, ALLOCATION OK 325$: MOV #PC.LOW!,R2 ;SET UP LOW POOL CONDITION 33$: CALL $PLTRQ ;REQUEST POOL MONITOR TASK 34$: .IFT ;DF,I$$CBP&K$$DAS ASL (SP)+ ; CLEAN THE STACK, AND SET CARRY AS NEEDED. .IFF ;DF,I$$CBP&K$$DAS ASL (R0) ;RECOVER THE CARRY BIT AND RESET LOC 0 .ENDC ;DF,I$$CBP&K$$DAS .ENDC 35$: RETURN ;DONE .IF DF R$$DER 40$: ; .IF DF P$$CTL .IF DF I$$CBP&K$$DAS ROR (SP) ; TRACKABLE POOL? BCC 43$ ; IF CC, NOPE, FINISH UP ... BIT #F6.ICP,$FMSK6 ; HAS THIS FUNCTION BEEN DISABLED BY LOA? BEQ 43$ ; IF EQ, YES, RETURN THE ERROR ASL (SP)+ ; WAS THIS ALREADY ICB POOL BEQ 45$ ; IF MOV #$ICAVL-2,R0 ; POINT TO ICB POOL LISTHEAD CALLR $ALOC1 ; AND RETRY THE ALLOCATION 43$: ASL (SP)+ ; CLEAN STACK, AND SET CARRY .IFF ;DF,I$$CBP&K$$DAS INC (SP)+ ;CLEAN STACK .ENDC ;DF,I$$CBP&K$$DAS 45$: .ENDC DEC R0 ;RETURN A VALUE OF MINUS ONE RETURN ; 50$: BGCK$A BF.POL,BE.FSI,FATAL ;ALLOCATION - FRAGMENT SIZE INVALID .ENDC .DSABL LSB ;+ ; **-$ALCLK-ALLOCATE CLOCK QUEUE CORE BLOCK ; ; THIS ROUTINE IS CALLED TO ALLOCATE A CORE BLOCK FOR A CLOCK QUEUE ENTRY. ; ; INPUTS: ; ; NONE. ; ; OUTPUTS: ; ; IF INSUFFICIENT CORE IS AVAILABLE TO ALLOCATE THE BLOCK, THEN A ; DIRECTIVE STATUS OF 'D.RS1' IS RETURNED. ELSE THE ADDRESS OF ; THE ALLOCATED BLOCK IS RETURNED TO THE CALLER IN R0. ;- .ENABL LSB $ALCLK::MOV #C.LGTH,R1 ;PICK UP LENGTH OF CLOCK BLOCK BR 10$ ; ;+ ; **-$DECLK-DEALLOCATE CLOCK QUEUE CORE BLOCK ; **-$DCLKA-DEALLOCATE CLOCK QUEUE BLOCK THAT MAY HAVE ACCOUNTING REQUIREMENTS ; ; THIS ROUTINE IS CALLED TO DEALLOCATE A CORE BLOCK THAT WAS BEING USED ; FOR A CLOCK QUEUE ENTRY. ; ; INPUTS: ; ; R0=ADDRESS OF THE CORE BLOCK TO BE DEALLOCATED. ; ; OUTPUTS: ; ; THE CLOCK QUEUE ENTRY CORE BLOCK IS DEALLOCATED. ;- $DCLKA:: .IF DF A$$CNT CMPB #C.SCHD,C.RQT(R0) ;PERIODIC TASK REQUEST BEQ 2$ ;IF EQ YES CMPB #C.SSHT,C.RQT(R0) ;SINGLE SHOT TASK REQUEST BNE $DECLK ;IF NE NO 2$: MOV C.UAB(R0),R1 ;LOCATE UAB BEQ $DECLK ;IF EQ, NO UAB MOV KISAR6,-(SP) ;SAVE CURRENT MAPPING MOV R1,KISAR6 ;MAP UAB DECB @#B.USE+140000 ;DECREMENT USE COUNT BNE 4$ ;IF NE, UAB IS STILL ACTIVE MOV R0,-(SP) ;SAVE R0 BICB #BS.ACT,@#B.STM+140000 ;DEACTIVATE UAB CALL $QACNT ;QUEUE UAB TO SYSLOG MOV (SP)+,R0 ;RESTORE CLQ BLOCK ADDRESS 4$: MOV (SP)+,KISAR6 ;RESTORE ORIGINAL MAPPING .ENDC $DECLK:: .IF DF N$$DIR ;NAMED DIRECTORY SUPPORT CMPB #C.SCHD,C.RQT(R0) ;PERIODIC TASK REQUEST? BEQ 5$ ;IF EQ, YES CMPB #C.SSHT,C.RQT(R0) ;SINGLE SHOT TASK REQUEST? BNE 7$ ;IF NE, NO 5$: TSTB C.NAM(R0) ;IS THERE A CONTEXT BLOCK? BEQ 7$ ;IF EQ, NO MOV C.CTX(R0),R1 ;GET CONTEXT BLOCK POINTER BEQ 7$ ;BR IF EQ, NONE EXISTS CALL $DLCTX ;DEALLOCATE CONTEXT BLOCK 7$: ;REFERENCE LABEL .ENDC ; DF N$$DIR MOV #C.LGTH,R1 ;PICK UP LENGTH OF CLOCK BLOCK BR $DEACB ; ;+ ; **-$ALPKT-ALLOCATE SEND OR I/O REQUEST CORE BLOCK ; ; THIS ROUTINE IS CALLED TO ALLOCATE A CORE BLOCK FOR A SEND OR I/O ; REQUEST QUEUE ENTRY. ; ; INPUTS: ; ; NONE. ; ; OUTPUTS: ; ; IF INSUFFICIENT CORE IS AVAILABLE TO ALLOCATE THE BLOCK, THEN A ; DIRECTIVE STATUS OF 'D.RS1' IS RETURNED. ELSE THE ADDRESS OF ; THE ALLOCATED BLOCK IS RETURNED TO THE CALLER IN R0. ;- $ALPKT::MOV #I.LGTH,R1 ;SET LENGTH OF I/O PACKET 10$: CALL $ALOCB ;ATTEMPT TO ALLOCATE BLOCK BCC 80$ ;IF CC SUCCESSFUL DRSTS D.RS1 ;ALLOCATION FAILURE ;+ ; **-$DEPKT-DEALLOCATE SEND OR I/O REQUEST CORE BLOCK ; ; THIS ROUTINE IS CALLED TO DEALLOCATE A CORE BLOCK THAT WAS BEING USED ; FOR A SEND OR I/O REQUEST QUEUE ENTRY. ; ; INPUTS: ; ; R0=ADDRESS OF THE CORE BLOCK TO BE DEALLOCATED. ; ; OUTPUTS: ; ; THE SEND OR I/O REQUEST QUEUE ENTRY CORE BLOCK IS DEALLOCATED. ;- $DEPKT::MOV #I.LGTH,R1 ;SET LENGTH OF I/O PACKET ;+ ; **-$DEACB-DEALLOCATE CORE BUFFER ; **-$DEAC1-DEALLOCATE CORE BUFFER (ALTERNATE ENTRY) ; ; THIS ROUTINE IS CALLED TO DEALLOCATE AN EXEC CORE BUFFER. THE BLOCK IS ; INSERTED INTO THE FREE BLOCK CHAIN BY CORE ADDRESS. IF AN ADJACENT ; BLOCK IS CURRENTLY FREE, THEN THE TWO BLOCKS ARE MERGED AND INSERTED ; IN THE FREE BLOCK CHAIN. ; ; INPUTS: ; ; R0=ADDRESS OF THE CORE BUFFER TO BE DEALLOCATED. ; R1=SIZE OF THE CORE BUFFER TO DEALLOCATE IN BYTES. ; R3=ADDRESS OF CORE ALLOCATION LISTHEAD-2 IF ENTRY AT $DEAC1. ; ; OUTPUTS: ; ; THE CORE BLOCK IS MERGED INTO THE FREE CORE CHAIN BY CORE ; ADDRESS AND IS AGCOMERATED IF NECESSARY WITH ADJACENT BLOCKS. ;- $DEACB::MOV #$CRAVL-2,R3 ;POINT TO ALLOCATION MASK WORD .IF DF I$$CBP&K$$DAS CMP R0,#$POOL ; IS THIS BLOCK IN ICB POOL? BHIS 20$ ; IF HIS, NOPE, NORMAL PRIMARY POOL MOV #$ICAVL-2,R3 ; POINT TO ICB POOL BR $DEAC1 ; AND GO DEALLOCATE pOOL 20$: .ENDC ;DF,I$$CBP&K$$DAS .IF DF Q$$OPT ADD (R3),R1 ;ROUND TO NEXT BOUNDARY BIC (R3)+,R1 ; BEQ 80$ ;IF EQ NO BLOCK TO RELEASE CMP R1,#I.LGTH ;LENGTH EQUAL TO I/O PACKET? BNE 30$ ;IF NE NO MOV #$PKMAX,R2 ;PNT TO MAX # OF PACKETS TO PREALLOCATE CMPB (R2),-(R2) ;MAX NUMBER PREALLOCATED? BLOS 30$ ;IF LOS YES ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 75. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH75==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL INC (R2) ;INDICATE ONE MORE AVAILABLE MOV -(R2),(R0) ;LINK PACKET INTO LIFO LIST MOV R0,(R2) ; RETURN ; .ENDC ;Q$$OPT $DEAC1::ADD (R3),R1 ;ROUND TO NEXT BOUNDARY BIC (R3)+,R1 ;CLEAR EXCESS BEQ 80$ ;IF EQ NO BLOCK TO RELEASE 30$: ;REF LABEL .IIF DF R$$DER!P$$CTL!C$$RTK MOV R3,-(SP) ;SAVE ADDRESS OF LISTHEAD 40$: MOV R3,R2 ;SAVE ADDRESS OF CURRENT BLOCK MOV (R2),R3 ;GET ADDRESS OF NEXT BLOCK BEQ 50$ ;IF EQ END OF CHAIN CMP R0,R3 ;BLOCK GO HERE? BHIS 40$ ;IF HIS NO 50$: MOV R3,(R0) ;ASSUME NO AGLOMERATION .IF DF P$$CTL CMP #$CRAVL,(SP) ;DEALLOCATION OF EXEC'S POOL? .IF DF,I$$CBP&K$$DAS BEQ $SPH74 ;IF EQ, YES, INCLUDE THE STATS CMP #$ICAVL,(SP) ; HOW ABOUT ICB POOL? .ENDC ;DF,I$$CBP&K$$DAS BNE 53$ ; IF NE, NOPE, FINISH UP ... ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 74. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH74==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL ADD R1,@#$PRISZ ;COUNT SIZE IN POOL TOTAL 53$: ; .ENDC ; DF P$$CTL MOV R0,-(SP) ;CALCULATE ADDRESS OF NEW BLOCK ADD R1,(SP) ; .IF DF R$$DER BCS 110$ ;IF CS, ILLEGAL DEALLOCATION CMP 2(SP),#$CRAVL ;DEALLOCATION IN EXECUTIVE POOL? BNE 55$ ;IF NE NO CMP R0,#$POOL ;DEALLOCATION BEFORE FRONT OF LIST? BLO 120$ ;IF LOW, YES CMP (SP),$EXSIZ ;DEALLOCATION PAST END OF POOL? BHI 130$ ;IF HIGH, YES 55$: ;REFERENCE LABEL .IFTF ;R$$DER CMP R3,(SP)+ ;EQUAL TO NEXT IN CHAIN? .IFT ;R$$DER BLO 90$ ;IF LO, DEALLOCATION OVERLAPS .IFTF ;R$$DER BNE 60$ ;IF NE NO MOV (R3)+,(R0) ;MOVE LINK WORD TO BLOCK RELEASED ADD (R3),R1 ;MERGE TWO BLOCKS 60$: MOV R2,-(SP) ;SAVE ADDRESS OF PREVIOUS BLOCK MOV R0,(R2)+ ;ASSUME NO AGLOMERATION ADD (R2),(SP) ;CALCULATE ADDRESS OF NEXT BLOCK CMP R0,(SP)+ ;EQUAL TO BLOCK BEING RELEASED? .IFT ;R$$DER BHIS 65$ ;IF HIS, NO OVERLAP CMP (SP),#$CRAVL ;DEALLOCATION IN EXECUTIVE CORE POOL? BEQ 100$ ;IF EQ YES (ELSE NOT SURE OF OVERLAP) 65$: ;REF LABEL .ENDC ;R$$DER BNE 70$ ;IF NE NO ADD (R2),R1 ;MERGE TWO BLOCKS MOV (R0),-(R2) ;MOVE LINK WORD TO PREVIOUS BLOCK MOV R2,R0 ;SET NEW ADDRESS OF BLOCK 70$: MOV R1,2(R0) ;SET SIZE OF BLOCK RELEASED .IF DF P$$CTL CMP #$CRAVL,(SP) ;ALLOCATION IN EXEC CORE POOL? .IF DF,I$$CBP&K$$DAS BEQ 73$ ; IF EQ, YES, CHECK FOR HIGH POOL CMP #$ICAVL,(SP) ; IF THIS ICB POOL? .ENDC ;DF,I$$CBP&K$$DAS BNE 75$ ;IF NE NO, SKIP DEALLOCATION CHECKS 73$: CMP $PRISZ,$PRIHL ;DID WE CROSS UPPER POOL LIMIT? BLE 75$ ;IF LE NO MOV #PC.HIH!,R2 ;SET UP HIGH POOL CONDITION TST (SP)+ ;CLEAN STACK BR $PLTRQ ;REQUEST POOL RECOVERY TASK 75$: .ENDC ;P$$CTL .IF DF C$$RTK CMP #$CRAVL,(SP)+ ;ALLOCATION IN CORE POOL? BNE 80$ ;NOPE, EXIT TST $CPPOL ;CPRSX COMMUNICATION DRIVER WAITING FOR POOL? BEQ 80$ ;NOPE, EXIT CALL $CPRCV ;LET CPR DRIVER USE THE POOL .IFF ;C$$RTK .IIF DF P$$CTL!R$$DER TST (SP)+ ;CLEAN STACK .ENDC ;C$$RTK 80$: RETURN ; .IF DF R$$DER 90$: TST R3 ;INSERT AT END OF LIST? BEQ 60$ ;IF EQ YES, OK 100$: BGCK$A BF.POL,BE.DDA,FATAL ;DOUBLE DEALLOCATION 110$: BGCK$A BF.POL,BE.SIZ,FATAL ;SIZE OF BLOCK INVALID 120$: BGCK$A BF.POL,BE.BAK,FATAL ;DEALLOCATED BLOCK BELOW POOL 130$: BGCK$A BF.POL,BE.POV,FATAL ;OVERLAPS END OF POOL .ENDC ;R$$DER .DSABL LSB ;+ ; **-$PLTRQ-REQUEST POOL MONITOR TASK ; ; THIS ROUTINE IS USED TO REQUEST THE EXECUTION OF THE POOL ; MONITOR TASK, IF INSTALLED. THE FORMAT OF THE POOL TASK/EXECUTIVE ; COMMUNICATIONS WORD IS AS FOLLOWS: ; ; $POLST CONTAINS CONDITION BITS INDICATING THE CUMULATIVE ; HISTORY OF THE POOL'S CONDITION SINCE THE LAST TIME ; THAT THE POOL MONITOR TASK CLEARED THEM. THESE BITS ; ARE SET BY THIS ROUTINE AND MAY BE CLEARED BY THE ; POOL MONITOR TASK. NOTE THAT MORE THAN ONE BIT MAY ; BE SET IN THIS BYTE AT ANY ONE TIME. ; $POLST+1 CONTAINS INHIBIT BITS INDICATING WHAT POOL CONDITIONS ; THE POOL MONITOR TASK IS CURRENTLY AWARE OF. A BIT SET ; IN THIS BYTE INDICATES TO THIS ROUTINE A POOL CONDITION ; THAT DOES NOT REQUIRE EXECUTION OF THE POOL MONITOR ; TASK. THESE BITS ARE ONLY MODIFIED BY THE POOL TASK. ; GENERALLY, THERE IS NEVER MORE THAN ONE BIT SET IN ; THIS BYTE AT ANY GIVEN TIME. ; ; THE CALLER OF THIS ROUTINE PROVIDES A BIT MASK INDICATING A ; POOL CONDITION THAT IT WISHES TO MAKE KNOWN TO THE POOL MONITOR ; TASK. THE GENERAL FORM OF THIS BIT MASK IS #>, ; WHERE 'XXX' DENOTES WHICH OF THE EIGHT POTENTIAL CONDITIONS THE ; USER WISHES TO MAKE KNOWN TO THE POOL MONITOR TASK (BY STORING ; THE PC.XXX BIT IN THE LOW BYTE OF $POLST). THE FOLLOWING ACTIONS ; CAN OCCUR: ; ; 1) IF THE SPECIFIED LOW BYTE MASK BIT IS ALREADY SET IN THE ; LOW BYTE OF $POLST, THEN THIS INDICATES THAT THIS ROUTINE HAS ; BEEN CALLED MULTIPLE TIMES FOR THE SAME POOL CONDITION BEFORE ; THE POOL TASK COULD EXECUTE AND CLEAR THE BIT. IN THIS CASE, ; THE ROUTINE RETURNS. ; ; 2) IF THE BIT IS NOT ALREADY SET IN THE LOW BYTE OF $POLST, ; THEN THIS INDICATES THAT THE POOL PROGRAM MIGHT NOT BE AWARE ; OF THIS POOL CONDITION AND A SECOND CHECK MUST BE MADE USING ; THE HIGH BYTE OF $POLST. IF THE SPECIFIED HIGH BYTE MASK BIT ; IS ALREADY SET IN THE HIGH BYTE, THEN THE POOL TASK IS ; CURRENTLY AWARE OF THE CONDITION AND DOES NOT WISH TO EXECUTE. ; IF THE BIT IS NOT SET IN THE HIGH BYTE, THEN THE POOL CONDITION ; IS A NEW ONE AND THE POOL MONITOR TASK IS REQUESTED TO RUN. ; ; THIS INTERFACE IS FLEXIBLE ENOUGH TO ALLOW OTHER INTERFACE PROTOCOLS: ; ; - ONE INHIBIT BIT ($POLST+1) COULD BE DEFINED TO 'COVER' MORE ; THAN ONE CONDITION BIT ($POLST+0). FOR INSTANCE, $PLTRQ CAN ; BE CALLED WITH R2=403, WHERE THERE ARE TWO CONDITION BITS SET, ; BUT ONLY ONE INHIBIT BIT SPECIFIED FOR BOTH. ; ; - THERE NEED NOT BE A MIRROR-IMAGE RELATIONSHIP BETWEEN THE ; INHIBIT BITS AND THE CONDITION BITS. FOR VARYING CONDITIONS ; AND STATES, VARIOUS COMBINATIONS OF THESE BITS CAN BE ENCODED. ; ; - NO INHIBIT BIT NEED BE SPECIFIED AT ALL. IN THIS CASE, EVEN ; IF THE POOL MONITOR TASK HAD SET THE CORRESPONDING INHIBIT BIT ; IN $POLST+1 FOR THE CONDITION ABOUT TO BE REPORTED, LEAVING ; THE HIGH BYTE OF R2 CLEAR WILL FORCE THE POOL MONITOR TASK TO ; EXECUTE FOR THAT CONDITION REPORTED IN THE LOW BYTE OF ; R2 (UNLESS, OF COURSE, THAT BIT IS ALREADY SET IN $POLST+0, ; INDICATING A MULTIPLE REQUEST). FOR INSTANCE, IF $PLTRQ IS ; CALLED WITH R2=1, THE POOL TASK MAY EXECUTE AND SET $POLST ; TO 400, THE INHIBIT BIT FOR POOL CONDITION '1'. IF $PLTRQ ; WERE THEN CALLED AGAIN WITH R2=1, THE POOL TASK WOULD AGAIN ; BE CALLED BECAUSE R2 DID NOT HAVE THE INHIBIT BIT SPECIFIED. ; THIS OPERATION FORCES THE POOL TASK TO RESPOND ANYWAY. ; ; THE REASON FOR SUCH FLEXIBILITY IS TO GENERALIZE THE INTERFACE TO ; BE USEFUL FOR A VARIETY OF CHORES. THE INTERFACE NEED NOT BE LIMITED ; TO POOL STATUS REPORTING. ; ; INPUTS: ; ; R2=POOL CONDITION BIT MASK (PC.XXX OR'ED WITH PC.XXX*400). ; ; OUTPUTS: ; ; IF NO BITS IN THE LOW BYTE OF R2 ARE SET IN $POLST AND NO ; BITS IN THE HIGH BYTE OF R2 ARE SET IN $POLST+1, THEN THE ; POOL TASK IS REQUESTED WITH THE REASON FOR THE REQUEST ; (PC.XXX) STORED IN THE LOW BYTE OF $POLST. OTHERWISE, RETURN. ; ; R0,R1 AND R3 ARE PRESERVED. ;- .ENABL LSB $PLTRQ:: .IF DF P$$CTL BITB R2,$POLST ;ALREADY REQUESTED FOR THIS CONDITION? BNE 20$ ;IF NE YES, AVOID MULTIPLE REQUESTS BISB R2,$POLST ;INDICATE CURRENT POOL CONDITION CLRB R2 ;CHECK POOL TASK INHIBIT BITS BIT R2,$POLST ;REQUEST POOL TASK FOR THIS CONDITION? BNE 20$ ;IF NE NO, TASK AWARE OF POOL CONDITION MOV R0,-(SP) ;SAVE R0 MOV $PTTCB,R0 ;POOL MONITOR TASK INSTALLED? BEQ 10$ ;IF EQ NO, CAN'T REQUEST IT MOV R1,-(SP) ;SAVE R1 MOV R3,-(SP) ;SAVE R3 CALL $EXRQN ;REQUEST THE POOL MONITOR TASK MOV (SP)+,R3 ;RESTORE R3 MOV (SP)+,R1 ;RESTORE R1 10$: MOV (SP)+,R0 ;RESTORE R0 20$: .ENDC ; DF P$$CTL RETURN ; .DSABL LSB ;+ ; **-$ALSEC-ALLOCATE CORE BUFFER FROM SECONDARY POOL ; **-$ALSC1-ALLOCATE 32 WORD BLOCKS OF POOL - ALTERNATE ENTRY ; ; ; THIS ROUTINE IS CALLED TO ALLOCATE A BLOCK FROM THE SECONDARY POOL. THE ; ALLOCATION ALGORITHM IS FIRST FIT (SAME AS $ALOCB). BLOCKS ARE ; ALLOCATED IN UNITS OF 32 WORDS, AND A BLOCK WILL ALWAYS START ON A 32 WD ; BOUNDRY TO FACILITATE MAPPING THE BLOCK. ; ; INPUTS: ; ; R1=SIZE OF THE BUFFER TO ALLOCATE IN 32 WORD BLOCKS ; R2=ADDRESS OF POOL LISTHEAD IF ENTRY AT $ALSC1 ; ; OUTPUTS: ; ; C=1 IF INSUFFICIENT CORE IS AVAILABLE TO ALLOCATE THE BLOCK ; R0=-1 ; ; C=0 IF THE ALLOCATION WAS SUCCESSFUL ; R0=ADDRESS OF BLOCK (TO BE USED IN AN APR) ; R1=SIZE OF BLOCK JUST ALLOCATED IN 32 WD UNITS ; ; R3, R4, R5 PRESERVED ACROSS CALL ; ;- $ALSEC:: .IF DF P$$OOL .IIF DF C$$SC1 MOV #$POLHD,R2 ;PUT $POLHD WHERE ROUTINE LOOKS FOR IT $ALSC1:: .ENABL LSB SAVNR ;SAVE R4, R5 .IF DF C$$SC1 ;IF ALTERNATE SECONDARY POOL MOV R3,-(SP) ;AND R3 MOV R2,R3 ;MOVE THE LISTHEAD .ENDC ;C$$SC1 MOV #-1,R0 ;ASSUME REQUESTED LENGTH IS 0 MOV #KISAR6,R4 ;POINT TO APR USED FOR POOL MAPPING MOV (R4),-(SP) ;SAVE CURRENT MAPPING MOV #140000,R2 ;VIRTUAL ADDRESS OF MAPPED POOL BLOCK CLR R5 ;PREVIOUS BLOCK IN LIST IS THE LISTHEAD TST R1 ;IS LENGTH ZERO? SEC ;ASSUME IT IS BEQ 50$ ;IF EQ YES .IIF DF C$$SC1 MOV (R3),(R4) ;MAP FIRST FREE BLOCK IN POOL .IIF NDF C$$SC1 MOV $POLHD,(R4) ;MAP FIRST FREE BLOCK IN POOL BR 20$ 10$: MOV (R4),R5 ;SAVE CURRENT BLOCK AS PREVIOUS MOV (R2),(R4) ;MAP TO NEXT BLOCK 20$: BEQ 50$ ;IF EQ, END OF LIST CMP 2(R2),R1 ;IS BLOCK BIG ENOUGH? BLO 10$ ;IF LO NO BEQ 30$ ;IF EQ YES, EXACT FIT MOV (R2)+,-(SP) ;SAVE LINK TO NEXT POOL BLOCK MOV (R2),-(SP) ;SAVE SIZE SUB R1,(SP) ;CALCULATE REMAINING SIZE ADD R1,(R4) ;MAP TO REMAINING PORTION OF BLOCK MOV (SP)+,(R2) ;GET REMAINING SIZE OF UNALLOCATED BLOCK MOV (SP),-(R2) ;INSERT LINK TO NEXT BLOCK MOV (R4),(SP) ;SAVE ADDRESS OF BLOCK SUB R1,(R4) ;MAP BACK TO BLOCK TO BE ALLOCATED MOV (SP)+,(R2) ;SAVE POINTER TO NEW BLOCK 30$: MOV (R4),R0 ;ADDRESS OF ALLOCATED BLOCK .IFDF C$$SC1 CMP R3,#$POLHD ;IS THIS SECONDARY POOL? CLC ;MAKE SURE CARRY STAYS CLEAR BNE 35$ ;NO, LEAVE TOTAL FREE SPACE ALONE .ENDC ;C$$SC1 SUB R1,$SECFR ;SUBTRACT AMOUNT ALLOCATED FROM TOTAL FREE 35$: MOV (R2),-(SP) ;GET ADDRESS OF NEXT FREE BLOCK MOV R5,(R4) ;MAP TO PREVIOUS BLOCK BEQ 40$ ;IF EQ, PREVIOUS BLOCK IS THE LISTHEAD MOV (SP)+,(R2) ;UNLINK ALLOCATED SECTION BR 50$ 40$: .IIF DF C$$SC1 MOV (SP)+,(R3) ;UNLINK ALLOCATED SECTION .IIF NDF C$$SC1 MOV (SP)+,$POLHD ;UNLINK ALLOCATED SECTION 50$: MOV (SP)+,(R4) ;RESTORE ORIGINAL KISAR6 MAPPING .IIF DF C$$SC1 MOV (SP)+,R3 ;RESTORE ORIGINAL CONTENTS OF R3 60$: RETURN ;+ ; **-$ALSPK-ALLOCATE A RECEIVE BY REFERENCE PACKET FROM SECONDARY POOL ; **-$ALVPK-ALLOCATE A PACKET FROM THE SECONDARY POOL ; ; THIS ROUTINE IS CALLED TO ALLOCATE A SECONDARY POOL BLOCK. ; THE PACKET IS MAPPED THROUGH APR 5. ; ; INPUTS: ; ; R1=SIZE OF BLOCK IN UNITS OF 32. WORDS ($ALVPK). ; ; OUTPUTS: ; ; C=0 IF A BLOCK HAS BEEN ALLOCATED. ; R0=120000 (THE PACKET IS MAPPED THROUGH APR5). ; KISAR5 IS SET UP TO MAP THE PACKET. ; C=1 IF INSUFFICIENT CORE IS AVAILABLE TO ALLOCATE THE BLOCK. ; DIRECTIVE STATUS OF D.RS1 IS RETURNED. ; ;- $ALSPK::MOV #/100,R1 ;GET SIZE TO ALLOCATE $ALVBK::CALL $ALSEC ;ALLOCATE A BLOCK BCS 65$ ;IF CS ALLOCATION FAILURE MOV R0,KISAR5 ;MAP THE PACKET THROUGH APR5 MOV #120000,R0 ;POINT TO FIRST WORD OF THE PACKET RETURN ;RETURN WITH C=0 65$: DRSTS D.RS1 ;ALLOCATION FAILURE ;+ ; **-$DESPK-DEALLOCATE RECEIVE BY REFERENCE PACKET TO SECONDARY POOL ; ; THIS ROUTINE IS CALLED TO DEALLOCATE A RECEIVE BY REFERENCE PACKET ; TO THE SECONDARY POOL. ; ; INPUTS: ; ; R0=ADDRESS OF PACKET TO BE DEALLOCATED. THIS MUST BE THE ; APR VALUE TO MAP THE FIRST 32. WORD SEGMENT OF THE BLOCK. ; ; OUTPUTS: ; ; NONE. ; ;- .IFTF $DESPK:: .IFT MOV #/100,R1 ;GET SIZE TO DEALLOCATE ;+ ; **-$DESEC-DEALLOCATE CORE BLOCK IN SECONDARY POOL ; **-$DESC1-DEALLOCATE 32-WORD CORE BLOCK INTO PRIVATE POOL ; ; THIS ROUTINE IS CALLED TO DEALLOCATE A SECONDARY POOL BLOCK. THE BLOCK ; IS INSERTED INTO THE FREE BLOCK CHAIN BY CORE ADDRESS. IF AN ADJACENT ; BLOCK IS CURRENTLY FREE, THEN THE TWO BLOCKS ARE MERGED. ; ; INPUTS: ; ; R0=ADDRESS OF CORE BLOCK TO BE DEALLOCATED. THIS MUST BE THE ; APR VALUE TO MAP THE FIRST 32 WORD SEGMENT OF THE BLOCK ; R1=SIZE OF THE BLOCK IN UNITS OF 32 WORDS. ; R2=ADDRESS OF POOL LISTHEAD IF ENTRY AT $DESC1 ; ; OUTPUTS: ; ; THE CORE BLOCK IS MERGED INTO THE FREE CORE CHAIN BY ADDRESS ; AND MERGED WITH ANY BORDERING BLOCKS IF POSSIBLE ; ; R3, R4, R5 PRESERVED ; ;- .IFTF $DESEC:: .IIF DF C$$SC1 MOV #$POLHD,R2 ;PUT $POLHD ADDRESS WHERE NEEDED $DESC1:: .IFT TST R1 ;IS LENGTH ZERO BEQ 140$ ;IF EQ YES SAVNR ;SAVE R4, R5 MOV R3,-(SP) ;SAVE R3 .IIF DF C$$SC1 MOV R2,-(SP) ;PUT THE LISTHEAD ON THE STACK .IF NDF X$$SEC .IF DF C$$SC1 ;IF ALTERNATE SECONDARY POOL CMP (SP),#$POLHD ;IS THIS REAL SECONDARY POOL? BNE 69$ ;NO, DON'T CHECK FOR IT BEING IN PARTITION .ENDC ;C$$SC1 MOV $PLPAR,R3 ;LOCATE PARTITION MOV P.REL(R3),R4 ;GET ITS STARTING ADDRESS CMP R4,R0 ;DOES BLOCK START IN PARTITION BHI 160$ ;IF HIGH, NO ADD P.SIZE(R3),R4 ;GET TOP ADDRESS IN PARTITION .IFTF ADD R1,R0 ;GET TOP ADDRESS OF BLOCK BCS 150$ ;CS- OVERFLOW....BAD DEALLOC LEN .IFT CMP R4,R0 ;DOES BLOCK END IN PARTITION BLO 170$ ;IF LOW, NO .ENDC SUB R1,R0 ;RESTORE BASE ADDRESS OF BLOCK 69$: .IIF DF C$$SC1 MOV @(SP),R3 ;GET THE ADDRESS OF THE FIRST FREE BLOCK .IIF NDF C$$SC1 MOV $POLHD,R3 ;GET THE ADDRESS OF THE FIRST FREE BLOCK MOV #140000,R4 ;GET VIRTUAL ADDRESS OF BLOCK MOV #KISAR6,R5 ;POINT TO MAPPING REGISTER MOV (R5),-(SP) ;SAVE CURRENT MAPPING CLR -(SP) ;WORD FOR STORING TOP OF PREVIOUS BLOCK CLR R2 ;INITIAL PREV. BLOCK IN LIST IS LISTHEAD 70$: MOV R3,(R5) ;MAP NEXT FREE BLOCK BEQ 95$ ;IF EQ, END OF LIST CMP R0,R3 ;DOES BLOCK GO BEFORE CURRENT BLOCK BLO 80$ ;IF LO YES BEQ 180$ MOV R3,(SP) ;GET ADDRESS OF CURRENT BLOCK ADD 2(R4),(SP) ;CALCULATE ITS TOP ADDRESS MOV R3,R2 ;STORE ADDRESS AS THE PREVIOUS BLOCK MOV (R4),R3 ;POINT TO NEXT BLOCK IN FREE LIST BR 70$ ; 80$: ADD R1,R0 ;GET TOP ADDRESS IN DEALLOCATED BLOCK CMP R0,R3 ;CAN IT BE COMBINED WITH THE NEXT BLOCK BNE 90$ ;IF NE NO MOV (R4)+,-(SP) ;SAVE LINK TO NEXT FREE BLOCK MOV (R4),-(SP) ;SAVE LENGTH SUB R1,R0 ;FIND START OF BLOCK BEING DEALLOCATED MOV R0,(R5) ;MAP IT MOV R1,(R4) ;INSERT TO LENGTH OF THE BLOCK ADD (SP)+,(R4) ;ADD LENGTH OF NEXT BLOCK MOV (SP)+,-(R4) ;LINK TO NEXT FREE BLOCK BR 100$ 90$: BHI 180$ ;IF HIGH, DEALLOCATED BLOCK OVERLAPS NEXT SUB R1,R0 ;GET BASE ADDRESS OF DEALLOCATED BLOCK 95$: MOV R0,(R5) ;MAP BLOCK BEING DEALLOCATED MOV R3,(R4) ;INSERT LINK TO NEXT BLOCK IN FREE LIST MOV R1,2(R4) ;INSERT LENGTH 100$: CMP (SP)+,R0 ;CAN BLOCK BE MERGED WITH PREVIOUS BLOCK BNE 110$ ;IF NE NO MOV (R4)+,-(SP) ;SAVE LINK TO NEXT FREE BLOCK MOV (R4),-(SP) ;AND LENGTH MOV R2,(R5) ;MAP PREVIOUS BLOCK IN FREE LIST ADD (SP)+,(R4) ;ADD LENGTH TO WHAT IS ALREADY THERE MOV (SP)+,-(R4) ;LINK TO NEXT BLOCK BR 130$ 110$: BHI 180$ ;IF HI, BLOCK OVERLAPS PREVIOUS BLOCK MOV R2,(R5) ;MAP PREVIOUS BLOCK BNE 120$ ;IF NE, THERE IS A PREVIOUS BLOCK .IIF DF C$$SC1 MOV 2(SP),R4 ;USE THE LIST HEAD AS THE PREVIOUS BLOCK .IIF NDF C$$SC1 MOV #$POLHD,R4 ;USE THE LIST HEAD AS THE PREVIOUS BLOCK 120$: MOV R0,(R4) ;LINK BLOCK BEING DEALLOCATED INTO CHAIN 130$: .IF DF C$$SC1 CMP 2(SP),#$POLHD ;WAS THIS A SECONDARY POOL DEALLOCATION? BNE 135$ ;NO, JUST CONTINUE .ENDC ;C$$SC1 ADD R1,$SECFR ;ADD AMOUNT DEALLOCATED TO TOTAL FREE 135$: MOV (SP)+,(R5) ;RESTORE ORIGINAL MAPPING .IIF DF C$$SC1 TST (SP)+ ;POP $POLHD ADDRESS MOV (SP)+,R3 ;RESTORE R3 140$: RETURN 150$: BGCK$A BF.POL,BE.SIZ,FATAL ;SIZE OF BLOCK INVALID 160$: BGCK$A BF.POL,BE.BAK,FATAL ;DEALLOCATED BLOCK BELOW POOL 170$: BGCK$A BF.POL,BE.POV,FATAL ;OVERLAPS END OF POOL 180$: BGCK$A BF.POL,BE.DDA,FATAL ;DOUBLE DEALLOCATION .DSABL LSB .ENDC .END